package cn.leedsoft.luma.test.design_pattern;

import org.junit.Test;

import java.util.concurrent.CountDownLatch;

/**
 * 单例模式
 * Created by leeds on 2016/5/27.
 *
 * 1、构造方法private
 * 2、在【类加载】阶段，初始化单例
 */
public class Singleton {
    @Test
    public void singleBeanUnsafe() {
        final CountDownLatch begin = new CountDownLatch(1);
        final CountDownLatch end = new CountDownLatch(20);

        for(int i=0; i<20; i++) {
            final int j = i;
            Thread t = new Thread(new Runnable() {//闭包，实例
                public void run() {
                    try {
                        System.out.printf("线程【%d】 waiting\n", j);
                        begin.await();//确保，开始执行测试之前，所有线程，处于预备状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    SingleBeanUnsafe.getInstance();
                    end.countDown();//确保，最后一个线程执行完测试，主线程才结束
                }
            });
            t.start();
        }
        try {
            System.out.println("2s后，测试开始--------------");
            Thread.sleep(1000 * 2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        begin.countDown();
        try {
            end.await();
            System.out.println("结束--------------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
    @Test
    public void singleBeansafe() {
        final CountDownLatch begin = new CountDownLatch(1);
        final CountDownLatch end = new CountDownLatch(20);

        for(int i=0; i<20; i++) {
            final int j = i;
            Thread t = new Thread(new Runnable() {//闭包，实例
                public void run() {
                    try {
                        System.out.printf("线程【%d】 waiting\n", j);
                        begin.await();//确保，开始执行测试之前，所有线程，处于预备状态
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    SingleBeanSafe.getInstance();
                    end.countDown();//确保，最后一个线程执行完测试，主线程才结束
                }
            });
            t.start();
        }
        try {
            System.out.println("2s后，测试开始--------------");
            Thread.sleep(1000 * 2);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        begin.countDown();
        try {
            end.await();
            System.out.println("结束--------------");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

    }
}
//声明在static模块，直接在【类加载】阶段初始化单例
class SingleBeanSafe {
    private static int id = 0;
    private SingleBeanSafe(){
        id++;
        System.out.printf("init for %d time\n", id);
    }
    private static SingleBeanSafe instance = new SingleBeanSafe();
    public static SingleBeanSafe getInstance() {
        return instance;
    }
}
//存在线程安全隐患
class SingleBeanUnsafe {
    private static int id = 0;
    private SingleBeanUnsafe(){
        id++;
        System.out.printf("init for %d time\n", id);
    }
    private static SingleBeanUnsafe instance;
    public static SingleBeanUnsafe getInstance() {
        if(instance == null) instance = new SingleBeanUnsafe();
        return instance;
    }
}